/*
* @file my_wifi.cpp
* @brief This file contains the implementation of the MyWifi class
* @author feiniao
* @version 1.0
* @date 2025-5-11
* @note This code is designed to work with ESP32-S3 and uses the ESP-IDF 5.2.3 framework.
*       It provides a WiFi connection functionality for the ESP32-S3.
*/


#include "my_wifi.h"


/*
* @brief MyWifi class constructor
* @note This function initializes the MyWifi object.
*/
MyWifi::MyWifi() {
    ESP_LOGI(TAG, "MyWifi对象创建成功!");
}


/*
* @brief Event handler for WiFi events
* @param arg Pointer to user data
* @param event_base Event base
* @param event_id Event ID
* @param event_data Pointer to event data
* @note This function handles various WiFi events such as connection, disconnection, and IP acquisition.
* It is registered as an event handler for WiFi events.
* The function is called when a WiFi event occurs.
* It handles events such as WiFi start, connection, disconnection, and IP acquisition.
*/
static void event_handler(void* arg, esp_event_base_t event_base,int32_t event_id, void* event_data)
{   
    if(event_base == WIFI_EVENT)
    {
        switch (event_id)
        {
        case WIFI_EVENT_STA_START:      //WIFI以STA模式启动后触发此事件
            esp_wifi_connect();         //启动WIFI连接
            break;
        case WIFI_EVENT_STA_CONNECTED:  //WIFI连上路由器后，触发此事件
            ESP_LOGI(TAG, "connected to AP");
            break;
        case WIFI_EVENT_STA_DISCONNECTED:   //WIFI从路由器断开连接后触发此事件
            esp_wifi_connect();             //继续重连
            ESP_LOGI(TAG,"connect to the AP fail,retry now");
            break;
        default:
            break;
        }
    }
    if(event_base == IP_EVENT)                  //IP相关事件
    {
        switch(event_id)
        {
            case IP_EVENT_STA_GOT_IP:           //只有获取到路由器分配的IP，才认为是连上了路由器
                ESP_LOGI(TAG,"get ip address");
                break;
        }
    }
}


/*
* @brief Initializes the WiFi station
* @return ESP_OK on success
* @note This function initializes the WiFi station mode and configures the WiFi settings.
* It sets the WiFi mode to station, configures the SSID and password, and starts the WiFi.
* It also registers event handlers for WiFi events and IP events.
* The function is called when the MyWifi object is created.
*/
esp_err_t MyWifi::wifi_sta_init() {
    ESP_ERROR_CHECK(esp_netif_init());  //用于初始化tcpip协议栈
    ESP_ERROR_CHECK(esp_event_loop_create_default());       //创建一个默认系统事件调度循环，之后可以注册回调函数来处理系统的一些事件
    esp_netif_create_default_wifi_sta();    //使用默认配置创建STA对象

    //初始化WIFI
    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK(esp_wifi_init(&cfg));
    
    //注册事件
    ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT,ESP_EVENT_ANY_ID,&event_handler,NULL));
    ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT,IP_EVENT_STA_GOT_IP,&event_handler,NULL));

    //WIFI配置
    wifi_config_t wifi_config = {
        .sta = {
            .ssid = DEFAULT_WIFI_SSID,
            .password = DEFAULT_WIFI_PASSWORD,
            .threshold = {
                .authmode = WIFI_AUTH_WPA2_PSK
            },
            .pmf_cfg = {
                .capable = true,
                .required = false
            }
        }
    };
    
    //启动WIFI
    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) );         //设置工作模式为STA
    ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config) );   //设置wifi配置
    ESP_ERROR_CHECK(esp_wifi_start() );                         //启动WIFI
    
    ESP_LOGI(TAG, "wifi_init_sta finished.");
    return ESP_OK;
}


/*
* @brief Disconnects the WiFi
* @note This function disconnects the WiFi and unregisters the event handlers.
* It stops the WiFi and deinitializes it.
*/
void MyWifi::disconnect_wifi() {
    esp_wifi_disconnect();  //断开连接
    esp_wifi_stop();        //停止WIFI
    esp_event_handler_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler);  //注销事件处理函数
    esp_event_handler_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler);  //注销事件处理函数
    esp_wifi_deinit();      //反初始化WIFI
    ESP_LOGI(TAG, "WIFI已断开!");
}


/*
* @brief Destructor for the MyWifi class
* @note This function is called when the MyWifi object is destroyed.
* It disconnects the WiFi and unregisters the event handlers.
* The function is called when the MyWifi object is destroyed.
*/
MyWifi::~MyWifi() {
    disconnect_wifi();
    ESP_LOGI(TAG, "MyWifi对象销毁成功!");
}


/*
* @brief Connects to the WiFi
* @note This function initializes the NVS flash, WiFi station, and SNTP.
*/
void MyWifi::connect_wifi() {
    nvs_flash_init();
    wifi_sta_init();
    initialize_sntp();
}


/*
* @brief Initializes the SNTP (Simple Network Time Protocol)
* @note This function sets the SNTP operating mode, server name, and initializes SNTP.
* It also waits for the time to be synchronized and logs the completion message.
*/
void MyWifi::initialize_sntp() {
    esp_sntp_setoperatingmode(SNTP_OPMODE_POLL);
    esp_sntp_setservername(0, "pool.ntp.org");
    esp_sntp_init();
    time_t now = 0;
    struct tm timeinfo = {0};
    int retry = 0;
    while (timeinfo.tm_year < (2024 - 1900) && ++retry < 10) {
        vTaskDelay(pdMS_TO_TICKS(2000));
        time(&now);
        localtime_r(&now, &timeinfo);
    }
    ESP_LOGI(TAG, "SNTP初始化完成!");
}
